package com.longqin.wechat.jwt;

import java.util.Date;
import java.util.Map;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.longqin.wechat.entity.AccessToken;
import com.longqin.wechat.entity.MyException;
import com.longqin.wechat.entity.User;
import com.longqin.wechat.util.ResponseEnum;


/**jwt工具类
 *
 */
public class JWTUtil {

    // 过期时间 24 小时
    private static final long EXPIRE_TIME =24* 3600 * 1000;
    //private static final long EXPIRE_TIME =15 * 1000;
    
    //刷新token的有效期24天(貌似最长的天数为24天)
    private static final long REFRESH_EXPIRE_TIME = 24 *24* 3600 * 1000;
    
    //longqin字符串的MD5加密
    private static final String SECRET = "82977808466efbb5f06ba5cc80bc80e0";

    /**获取token信息
     * @param username
     * @return
     * @throws Exception
     */
    public static AccessToken getAccessToken(User user)  {
    	try {
			return new AccessToken(sign(user), refreshSign(user), EXPIRE_TIME,
					user.getWeChatUserInfo(), user.getUserName(), user.getUserId(), user.getOrganizationId());
		} catch (Exception e) {
			return null;
		}
    }
    
    /**
     * @Description:  刷新token
     * @param refreshToken
     * @return
     * @throws Exception
     * 
     */
    public static AccessToken refreshToken(String refreshToken) throws Exception {
    	 Map<String,Claim> map = getJWTClaim(refreshToken);
    	 if(null == map || !map.get("tokenType").asString().equals("refresh_token"))
    		 throw new MyException(ResponseEnum.ERROR.getCode(), "输入的refresh_token无效");
    	 User user= new User(map.get("userId").asInt(), map.get("userName").asString(), map.get("nickName").asString());
    	 user.setOrganizationId(map.get("orgId").asInt());
    	 return new AccessToken(sign(user), refreshSign(user), EXPIRE_TIME,null);		 
    }
    
 
    /**
     * @Description: 生成token,一天后过期
     * @param user
     * @return
     * @throws Exception
     * 
     */
    public static String sign(User user) throws Exception{
    	Date date = new Date(System.currentTimeMillis()+EXPIRE_TIME);
    	Algorithm algorithm = Algorithm.HMAC256(SECRET);
    	JWTCreator.Builder jb=JWT.create();
    	return jb.withClaim("userId", user.getUserId())
         	   	 .withClaim("userName", user.getUserName())
         	   	 .withClaim("nickName", user.getNickName())
         	   	 .withClaim("orgId", user.getOrganizationId())
    			 .withClaim("tokenType", "access_token")
    			 .withExpiresAt(date).sign(algorithm);
    }
    
    
    /**
     * @Description: 生成token,30天后过期
     * @param user
     * @return
     * @throws Exception
     * 
     */
    private static String refreshSign(User user) throws Exception {
        Date date = new Date(System.currentTimeMillis()+REFRESH_EXPIRE_TIME);
        Algorithm algorithm = Algorithm.HMAC256(SECRET);
        JWTCreator.Builder jb=JWT.create();
        return jb.withClaim("userId", user.getUserId())
        	   	 .withClaim("userName", user.getUserName())
        	   	 .withClaim("nickName", user.getNickName())
        	   	 .withClaim("orgId", user.getOrganizationId())
        		 .withClaim("tokenType", "refresh_token")
                 .withExpiresAt(date).sign(algorithm);
    }
   

    /**
     * 校验token是否正确
     * @param token 密钥
     * @param secret 用户的密码
     * @return 是否正确
     */
    public static boolean verify(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(token);
            return true;
        } catch (Exception exception) {
            return false;
        }
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     * @return token中包含的用户名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("userName").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }
    
    /**获取token包含的信息（主要为当前账号信息）
     * @param token
     * @return
     * @throws Exception
     */
    public static Map<String, Claim> getJWTClaim(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaims();
        } catch (JWTDecodeException e) {
            throw new MyException(ResponseEnum.TOKENEXPIRED.getCode(), "token失效请重新登录");
        }
    }
    
    /**获取token包含的组织id
     * @param jwt
     * @return
     */
    public static Integer getOrganizationID(String jwt) {
        Map<String, Claim> jwtClaim = JWTUtil.getJWTClaim(jwt);
        Integer  organizationID = jwtClaim.get("orgId").asInt();
        return organizationID;
    }
}
